(function($){
    
    var methods = {
        init : function( opcoes ) { 
            var config = {
                selectable: false,
                multiple_selection: false,
                show_expand_button: true,
                selection_color: "#FAFAD2"
            }

            $.extend(config, opcoes);

            return this.each(function(){
                var componente_pai = $(this);
                var pai_id = componente_pai.attr("id");

                // Criando os elementos
                if (config.cabecalho){
                    var thead = $("<thead>"+config.cabecalho+"</thead>");
                
                    var colunas = thead.find("th").length;

                    if (config.selectable){
                        colunas ++;
                        var th = $("<th></th>");
                        thead.children("tr").eq(0).prepend(th);
                        if (config.selectable){
                            var check_all = $("<input id='"+pai_id+"_checkbox_multiple_selection'type='checkbox'/>");
                            check_all.change(function(event){
                                var source = $(this);
                                if (source.attr("checked") == "checked"){
                                    for (var i in myPaginator.dados_response){
                                        if (! methods.is_selected.call(componente_pai, i)){
                                            methods.select_row.call(componente_pai, i);
                                        }
                                    }
                                }else{
                                    for (var i in myPaginator.dados_response){
                                        if ( methods.is_selected.call(componente_pai, i)){
                                            methods.select_row.call(componente_pai, i);
                                        }
                                    }
                                }
                            });
                            if (!config.multiple_selection){
                                check_all.prop("disabled", true);
                            }
                            th.append(check_all);
                        }

                    }

                    if ( config.detalhe && config.show_expand_button){
                        colunas++;
                        thead.children("tr").eq(0).prepend("<th></th>");
                    }

                    // alinho o cabecalho a esquerda
                    thead.find("th").css("text-align", "left");
                }
                
                
                var tbody = $("<tbody></tbody>");
                var tfoot = $("<tfoot></tfoot>");
                var tr_foot = $('<tr id="'+pai_id+'_rodape"></tr>');
                var td_foot = $('<td colspan="'+colunas+'"></td>');
                var form_parametros = $('<form id="'+pai_id+'_parametros"></form>');
                var form_rows = $('<select name="rows">'+
                        '<option value="10" >10</option>'+
                        '<option value="20" >20</option>'+
                        '<option value="30" >30</option>'+
                        '<option value="40" >40</option>'+
                        '<option value="50" >50</option>'+
                    '</select>');
                var form_button_primeiro = $('<button>&lt;&lt;</buton>');
                var form_button_anterior = $('<button>&lt;</buton>');
                var form_page = $('<input type="text" size="2" value="1" name="page"/>');
                var form_page_final = $('<span id="page_final">0</span>');
                var form_button_proximo = $('<button>&gt;</buton>');
                var form_button_ultimo = $('<button>&gt;&gt;</buton>');
                var form_itens = $('<span id="itens"> | Exibindo item(ns) 0 a 0 de 0</span>');
                
                var processa_resultado = function processa_resultado(response){
                    var rows = eval(myPaginator.form_rows.val());
                    var total = eval(response["total"]);

                    myPaginator.item1 = (myPaginator.page-1)*rows +1;
                    myPaginator.item2 = (myPaginator.page * rows) < total ? (myPaginator.page * rows) : total;
                    myPaginator.page_final = (total/rows) % 2 == 0 || (total/rows) == 1 ? (total/rows) : parseInt(total/rows) +1 ;
                    form_page.attr("value", myPaginator.page);
                    form_page_final.html(myPaginator.page_final);

                    form_itens.html(" | Exibindo item(ns) "+myPaginator.item1+" a "+myPaginator.item2+" de "+total);

                    if(myPaginator.page == 1){
                        form_button_primeiro.prop("disabled", true);
                        form_button_anterior.prop("disabled", true);
                    }else{
                        form_button_primeiro.prop("disabled", false);
                        form_button_anterior.prop("disabled", false);
                    }

                    if(myPaginator.page == myPaginator.page_final){
                        form_button_proximo.prop("disabled", true);
                        form_button_ultimo.prop("disabled", true);
                    }else{
                        form_button_proximo.prop("disabled", false);
                        form_button_ultimo.prop("disabled", false);
                    }

                    if(response["total"] == 0){
                        tbody.html("<tr  style='text-align: center; font-size: 12px; height: 40px; font-weight: bold; color: #006600; border-bottom: 1px solid #999999; margin-bottom: 2px;'><td colspan='"+colunas+"'>Nenhum resultado encontrado<td></tr>");
                        form_itens.html(" | Exibindo item(ns) 0 a 0 de 0");
                        return false;
                    }

                    var dados = response["rows"];
//                    var conteudo = "";
                    tbody.html("");
                    myPaginator.dados_response = dados;
                    myPaginator.rows_selecionadas = [];
                    
                    for(var i=0; i < dados.length; i++){
                        //Crio o dive do conteudo
                        var linha = $(config.conteudo(i, dados[i]));
                        linha.attr("id",pai_id+"_row_"+i);
                        
                        if (config.selectable){
                            var td = $("<td></td>");
                            linha.prepend(td);
                            if (config.selectable){
                                var check = $('<input id="'+pai_id+"_check_"+i+'" type="checkbox"/>');
                                check.bind("change", {i:i},function(event){
                                    methods.select_row.call(componente_pai, event.data.i);
                                });
                                td.append(check);
                            }
                        }
                        
                        if (config.detalhe){
                            if (config.show_expand_button){
                                var td = $("<td></td>");
                                linha.prepend(td);

                                var button_expand = $("<div style='cursor: pointer; display: inline-block; width: 16px; height: 16px; background: url(imagens/expand.png);'></div>");
                                button_expand.attr("id",pai_id+"_expandable_button_"+i);
                                button_expand.bind("click", {row_index:i}, function(event){
                                    methods.expand_row.call(componente_pai, event.data.row_index);
                                });
                                td.append(button_expand);
                            }
                            
                            var linha_expansivel = $("<tr style='border-bottom: 1px solid #999999; margin-bottom: 2px;'><td></td><td colspan='"+eval(colunas-1)+"'>"+config.detalhe(i, dados[i])+"</td></tr>");
                            linha_expansivel.attr("id",pai_id+"_expandable_row_"+i);
                            linha_expansivel.css("display", "none");

                        }
                        
                        if (config.duplo_click){
                            linha.bind("dblclick", {row_index: i} ,function(event){
                                config.duplo_click(event.data.row_index, myPaginator.dados_response[event.data.row_index]);
                            });
                            linha.css("cursor", "default");
                        }
                        
                        tbody.append(linha);
                        if (config.detalhe){
                            tbody.append(linha_expansivel);
                        }
                    }
                }

                var myPaginator = {
                    config: config,
                    pai_id: pai_id,
                    colunas: colunas,
                    page: 1,
                    page_final: 1,
                    item1: 0,
                    item2: 0,
                    check_all: check_all,
                    div_rodape: tr_foot,
                    div_conteudo: tbody,
                    form_rows: form_rows,
                    form_button_primeiro: form_button_primeiro,
                    form_button_anterior: form_button_anterior,
                    form_page: form_page,
                    form_page_final: form_page_final,
                    form_button_proximo: form_button_proximo,
                    form_button_ultimo: form_button_ultimo,
                    form_itens: form_itens,
                    processa_resultado: processa_resultado,
                    dados_form: $(config.formulario).serialize(),
                    dados_response: new Array(),
                    rows_selecionadas : new Array()
                }
                
                componente_pai.data("myPaginator", myPaginator);


                // configurando os elementos
                form_parametros.submit(function(evento){
                    evento.preventDefault();
                    methods.consultar.call(componente_pai, myPaginator.form_page.val());
                });
                form_button_primeiro.click(function(){
                    methods.consultar.call(componente_pai, 1);
                });
                form_button_proximo.click(function(){
                    methods.consultar.call(componente_pai, myPaginator.page + 1);
                });
                form_button_anterior.click(function(){
                    methods.consultar.call(componente_pai, myPaginator.page - 1);
                });
                form_button_ultimo.click(function(){
                    methods.consultar.call(componente_pai, myPaginator.page_final);
                });
                form_rows.change(function(){
                    methods.consultar.call(componente_pai, 1);
                });


                // Juntando os elementos
                if (thead) componente_pai.append(thead);
                
                componente_pai.append(tbody);
                componente_pai.append(tfoot);
                tfoot.append(tr_foot);
                tr_foot.append(td_foot);
                td_foot.append(form_parametros);
                form_parametros.append(form_rows);
                form_parametros.append("&nbsp;");
                form_parametros.append(form_button_primeiro);
                form_parametros.append("&nbsp;");
                form_parametros.append(form_button_anterior);
                form_parametros.append("&nbsp;Pagina&nbsp;");
                form_parametros.append(form_page);
                form_parametros.append("&nbsp;de&nbsp");
                form_parametros.append(form_page_final);
                form_parametros.append("&nbsp;");
                form_parametros.append(form_button_proximo);
                form_parametros.append("&nbsp;");
                form_parametros.append(form_button_ultimo);
                form_parametros.append(form_itens);
                
                methods.consultar.call(this, 1);

                
            });
        },
        consultar : function(page_to_go) {
            var div_pai = $(this);
            var myPaginator = div_pai.data("myPaginator");
            
            var rows = myPaginator.form_rows.val();
            
            // Valida o valor de page
            if (!isNaN(page_to_go)){
                if ((page_to_go > myPaginator.page_final && myPaginator.page_final > 0) || page_to_go < 1){
                    alert("Página inexistente!");
                    myPaginator.form_page.attr("value", myPaginator.page);
                    return false;
                }
            }
            else{
                alert("O valor digitado deve ser numérico!");
                myPaginator.form_page.attr("value", myPaginator.page);
                return false;
            }

            myPaginator.page = page_to_go;
            myPaginator.div_conteudo.html("<tr  style='text-align: center; font-size: 12px; height:40px; font-weight: bold; color: #006600; border-bottom: 1px solid #999999; margin-bottom: 2px;'><td colspan='"+myPaginator.colunas+"'>Aguarde...</td></tr>");
            $.ajax({
              type: 'POST',
              url: myPaginator.config.url,
              data: {
                page: page_to_go,
                rows: rows,
                consulta: myPaginator.dados_form
                },
              success: function(response){myPaginator.processa_resultado(response);},
              error: function(response){alert("Erro: ");},
              dataType: "json"
//                    success: function(response){ $("#erro").html(response)},
//                    dataType: "html"
            });
            methods.unselect_all.call(this);

            return false;
        },
        update : function( opcoes ) {
            var div_pai = $(this);
            var myPaginator = div_pai.data("myPaginator");
            if (myPaginator){
                var config = myPaginator.config;
                $.extend(config, opcoes);
                myPaginator.dados_form = $(config.formulario).serialize();
                methods.consultar.call(this, 1);
                methods.unselect_all.call(this);
            }else{
                $.error("Object myPaginator does not exist");
            }
        },
        reload : function( opcoes ) {
            var div_pai = $(this);
            var myPaginator = div_pai.data("myPaginator");
            if (myPaginator){
                var config = myPaginator.config;
                $.extend(config, opcoes);
                myPaginator.dados_form = $(config.formulario).serialize();
                methods.consultar.call(this, myPaginator.page);
                methods.unselect_all.call(this);
            }else{
                $.error("Object myPaginator does not exist");
            }
        },
        
        select_row: function( row_indice ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            
            if (myPaginator.config.selectable){
                var selected = false;
                var indice_selection;
                for(var j in myPaginator.rows_selecionadas){
                    if(myPaginator.rows_selecionadas[j] == myPaginator.dados_response[row_indice]){
                        selected = true;
                        indice_selection = j;
                    }
                }
                if (selected){
                    $("#"+myPaginator.pai_id+"_row_"+row_indice).css("background-color", "");
                    $("#"+myPaginator.pai_id+"_check_"+row_indice).removeAttr("checked");
                    myPaginator.rows_selecionadas.splice(indice_selection, 1);
                }else{
                    if (! myPaginator.config.multiple_selection){
                        for (var j in myPaginator.dados_response){
                            if(j != row_indice){
                                $("#"+myPaginator.pai_id+"_row_"+j).css("background-color", "");
                                $("#"+myPaginator.pai_id+"_check_"+j).removeAttr("checked");
                            }
                        }
                        myPaginator.rows_selecionadas = [];
                    }
                    myPaginator.rows_selecionadas.push(myPaginator.dados_response[row_indice]);
                    $("#"+myPaginator.pai_id+"_check_"+row_indice).attr("checked", "checked");
                    $("#"+myPaginator.pai_id+"_row_"+row_indice).css("background-color", myPaginator.config.selection_color);
                }
            }
        },
        unselect_all: function() {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            myPaginator.check_all.prop("checked", false);
            for (var j in myPaginator.dados_response){
                $("#"+myPaginator.pai_id+"_row_"+j).css("background-color", "");
                $("#"+myPaginator.pai_id+"_check_"+j).removeAttr("checked");
            }
            myPaginator.rows_selecionadas = [];
        },
        
        is_selected: function( row_indice ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            
            if (myPaginator.config.selectable){
                for(var j in myPaginator.rows_selecionadas){
                    if(myPaginator.rows_selecionadas[j] == myPaginator.dados_response[row_indice]){
                        return true;
                    }
                }
            }
            return false; 
        },
        
        get_selection: function( ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            
            if( myPaginator.rows_selecionadas.length > 0){
                return myPaginator.rows_selecionadas[0];
            }
            return null;
        },
        
        get_selections: function( ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            
            if( myPaginator.rows_selecionadas.length > 0){
                return myPaginator.rows_selecionadas;
            }
            return null;
        },
        
        expand_row: function(row) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            
            var componente = $("#"+myPaginator.pai_id+"_expandable_row_"+row);
            if (componente.data("expanded")){
                $("#"+myPaginator.pai_id+"_expandable_button_"+row).css("background-position", "0");
                componente.hide();
                componente.data("expanded", false);
            }else{
                $("#"+myPaginator.pai_id+"_expandable_button_"+row).css("background-position", "16px");
                componente.show();
                componente.data("expanded", true);
            }
            
        },
        enable_multiple_selection: function( ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            if(myPaginator.config.selectable){
                myPaginator.config.multiple_selection = true;
                myPaginator.check_all.prop("disabled", false);
                methods.unselect_all.call(componente_pai);
            }else{
                $.error("This paginator isn't selectable");
            }
            return null;
        },
        disable_multiple_selection: function( ) {
            var componente_pai = $(this);
            var myPaginator = componente_pai.data("myPaginator");
            if(myPaginator.config.selectable){
                myPaginator.config.multiple_selection = false;
                myPaginator.check_all.prop("disabled", true).prop("checked", false);
                methods.unselect_all.call(componente_pai);
            }else{
                $.error("This paginator isn't selectable");
            }
            return null;
        }
    };

    $.fn.tablePaginator = function( method ) {
    
        // Method calling logic
        if ( methods[method] ) {
          return methods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ));
        } else if ( typeof method === 'object' || ! method ) {
          return methods.init.apply( this, arguments );
        } else {
          $.error( 'Method ' +  method + ' does not exist on jQuery.myPaginator' );
        }
  
    };

})(jQuery);